# -*- coding: utf-8 -*-
import time
from .database import db,CRUDMixin
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index
from typing import Optional
from .base import BaseModel
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired
from werkzeug.security import generate_password_hash, check_password_hash

from flask import current_app,Blueprint

from flask import Flask, abort, request, jsonify, g, url_for
from flask_httpauth import HTTPBasicAuth
from flask_login import UserMixin
import base64

from app.common.extensions import login_manager

from app.common import code, pretty_result

auth = HTTPBasicAuth()

class UserModel(CRUDMixin,db.Model,BaseModel,UserMixin):
    __tablename__ = 'user'
    username:str = db.Column(db.String(64),comment='用户名')
    password_hash:str = db.Column(db.String(256),comment='哈希密码')
    age:Optional[str] = db.Column(db.String(32),comment='年龄')
    addr:Optional[str] = db.Column(db.String(128),default = '暂无',comment = '地址信息')
    
    def __init__(self,username, **kwargs):
        super(UserModel, self).__init__(**kwargs)
        self.username = username

    def hash_password(self, password):
        self.password_hash = generate_password_hash(password)
        print('password: %s' %(self.password_hash))

    def verify_password(self, password):
        self.hash_password(password)
        result = check_password_hash(self.password_hash, password)
        print('verify_password: %s' % result)
        return result

    def generate_auth_token(self, expires_in=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expires_in = expires_in)
        token = s.dumps({'username': self.username ,
            'uid':self.id})
        return token

    @staticmethod
    def verify_auth_token(token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except SignatureExpired:
            return None # valid token, but expired
        except BadSignature:
            return None # invalid token

        if 'uid' not in data or 'username' not in data:
            return None

        uid = data['uid']
        return UserModel.query.filter_by(id=uid).first()


@auth.verify_password
def verify_password(username_or_token, password):
    # first try to authenticate by token
    if not username_or_token:
        username_or_token = request.args.get('token')
    if not password:
        password = request.args.get('password')
    if not username_or_token:
        return False

    user = UserModel.verify_auth_token(username_or_token)
    if not user:
        # try to authenticate with username/password
        user = UserModel.query.filter_by(username=username_or_token).first()
        if not user or not user.verify_password(password):
            return False
    g.user = user
    return True


@auth.error_handler
def unauthorized():
    return pretty_result(code=code.AUTHORIZATION_ERROR,msg='Unauthorized access')

@login_manager.user_loader
def load_user(userid):
    return UserModel.query.get(int(userid))